<template>
  <div class="tinymce-prevent-delete-container">
    <editor v-model="content" :init="editorConfig" :api-key="apiKey" />
    <div v-if="showWarning" class="warning-message">
      警告：不能删除全部内容，请至少保留可编辑区域进行修改
    </div>
  </div>
</template>

<script>
import Editor from '@tinymce/tinymce-vue'

export default {
  components: {
    Editor
  },
  data() {
    return {
      apiKey: '你的TinyMCE API密钥',
      content: `
        <p>这是不能编辑的文本【这部分可以编辑】这部分也不能编辑</p>
        <p>多行示例：
          姓名：【请输入姓名】，
          年龄：【请输入年龄】，
          职业：【请输入职业】
        </p>
      `,
      originalContent: '', // 用于保存原始内容结构
      showWarning: false
    }
  },
  created() {
    // 保存初始内容结构用于恢复
    this.originalContent = this.content
  },
  computed: {
    editorConfig() {
      const that = this
      return {
        height: 400,
        menubar: 'edit format',
        toolbar: 'undo redo | bold italic | cut copy paste',
        readonly: false,
        extended_valid_elements: 'span[contenteditable|class|id]',
        contextmenu: 'undo redo | cut copy paste',
        setup: (editor) => {
          // 内容处理：替换标记
          editor.on('BeforeSetContent', (e) => {
            e.content = that.processContent(e.content)
          })

          // 内容获取：还原标记
          editor.on('GetContent', (e) => {
            e.content = that.restoreContent(e.content)
          })

          editor.on('init', () => {
            const doc = editor.getDoc()

            // 添加样式区分
            const style = doc.createElement('style')
            style.textContent = `
              .editable-section {
                border: 1px dashed #42b983;
                padding: 2px 4px;
                margin: 0 2px;
                border-radius: 3px;
                background-color: rgba(66, 185, 131, 0.1);
              }
              .non-editable {
                user-select: text;
              }
            `
            doc.head.appendChild(style)

            // 初始化可编辑状态
            that.setNonEditableAreas(editor)
          })

          // 控制命令执行范围
          editor.on('ExecCommand', (e) => {
            const isInEditable = that.isCursorInEditable(editor)
            // 只有在可编辑区域才能执行编辑命令
            if (!isInEditable) {
              e.preventDefault()
              e.stopPropagation()
              return false
            }
          })

          // 监控内容变化，防止全部删除
          editor.on('Change', () => {
            that.checkContentIntegrity(editor)
          })

          // 监控键盘删除操作
          editor.on('KeyDown', (e) => {
            // 处理删除键和退格键
            if (e.key === 'Delete' || e.key === 'Backspace') {
              that.preventFullDelete(editor, e)
            }
          })

          // 监控选择区域变化
          editor.on('NodeChange', () => {
            const isInEditable = that.isCursorInEditable(editor)
            that.toggleToolbarButtons(editor, isInEditable)
          })
        }
      }
    }
  },
  methods: {
    // 处理内容标记
    processContent(content) {
      let processed = `<div class="non-editable" contenteditable="false">${content}</div>`
      processed = processed.replace(
        /【([^】]+)】/g,
        (match, text) => `<span class="editable-section" contenteditable="true">${text}</span>`
      )
      return processed
    },

    // 还原内容标记
    restoreContent(content) {
      let restored = content.replace(
        /<div class="non-editable" contenteditable="false">([\s\S]*?)<\/div>/,
        '$1'
      )
      restored = restored.replace(
        /<span class="editable-section" contenteditable="true">([\s\S]*?)<\/span>/g,
        (match, text) => `【${text}】`
      )
      return restored
    },

    // 设置非编辑区域
    setNonEditableAreas(editor) {
      const doc = editor.getDoc()
      const nonEditable = doc.querySelectorAll('.non-editable')
      nonEditable.forEach((el) => {
        el.contentEditable = false
      })
      const editable = doc.querySelectorAll('.editable-section')
      editable.forEach((el) => {
        el.contentEditable = true
      })
    },

    // 判断光标是否在可编辑区域内
    isCursorInEditable(editor) {
      const node = editor.selection.getNode()
      return node.closest('.editable-section') !== null
    },

    // 切换工具栏按钮状态
    toggleToolbarButtons(editor, isEnabled) {
      const toolbarButtons = ['bold', 'italic', 'cut', 'copy', 'paste']
      toolbarButtons.forEach((button) => {
        editor.execCommand('mceToggleToolbarItem', false, button, !isEnabled)
      })
    },

    // 检查内容完整性，防止全部删除
    checkContentIntegrity(editor) {
      const content = editor.getContent({ format: 'text' }).trim()
      // 如果内容为空或只剩下空格，恢复原始内容结构
      if (content === '') {
        this.showWarning = true
        // 短暂延迟后隐藏警告
        setTimeout(() => {
          this.showWarning = false
        }, 3000)
        // 恢复内容（保留用户对可编辑区域的修改）
        editor.setContent(this.processContent(this.originalContent))
        this.setNonEditableAreas(editor)
      }
    },

    // 防止通过键盘完全删除内容
    preventFullDelete(editor, e) {
      const content = editor.getContent({ format: 'text' }).trim()
      const selection = editor.selection.getContent({ format: 'text' }).trim()

      // 如果选择了全部内容或内容即将被删空
      if (selection === content || (content.length <= 1 && selection === '')) {
        e.preventDefault()
        e.stopPropagation()
        this.showWarning = true
        setTimeout(() => {
          this.showWarning = false
        }, 3000)
      }
    }
  }
}
</script>

<style scoped>
.tinymce-prevent-delete-container {
  max-width: 900px;
  margin: 20px auto;
  padding: 0 20px;
}

.warning-message {
  margin-top: 10px;
  padding: 8px 12px;
  background-color: #fff3cd;
  border: 1px solid #ffeeba;
  border-radius: 4px;
  color: #856404;
  font-size: 14px;
  animation: fadein 0.5s, fadeout 0.5s 2.5s;
}

@keyframes fadein {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes fadeout {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}
</style>
